'''
Created on 10/08/2009

@author: eh01
'''
from Queue import Queue
from datastore import database, uritest
from datastore.database import DataStore
from datastore.resource import Resource
from datastore.uri import Uri
from runtime import rt
from runtime.spaces import Spaces, SpacesContext
from runtime.task import NonTaskException, Task
import os
import thread
import time
import unittest
#from helper import testhelper

cur_dir =  os.path.dirname(__file__)
yarra_dir = cur_dir + '/../../../'
config_files = []
for root, dirs, files in os.walk(yarra_dir):
    if files:
        for file in files:
            path = root.replace("\\", "/") + "/" + file
            if file == 'configuration.xml':
                res = Resource()
                res.load_from_file(path)
                config_files.append(res)

DATABASE_NAME = 'node.db3'

def initialise_spaces_with_local_config_files(rt):
    """This function initalises spaces from configuration.
    
    The method is passed a instance of SpacesContext which it uses to initialises spaces with:
    - all the uri namespaces bindings in either the configuration files found on the
    local file system.
    - the configuration files. 
    
    NOTE: This is solely used for writing tests at the moment.
    
    :param spaces_context: runtime.spaces.SpacesContext - SpacesContext used to initialise spaces.
    """
    
    cur_dir =  os.path.dirname(__file__)
    yarra_dir = cur_dir + '/../../../'
    config_file_rs_list = []
    for root, dirs, files in os.walk(yarra_dir):
        if files:
            for file in files:
                path = root.replace("\\", "/") + "/" + file
                if file == 'configuration.xml':
                    res = Resource()
                    res.load_from_file(path)
                    config_file_rs_list.append(res)
    rt.initialise_spaces(config_file_rs_list)
    
class RTTest(unittest.TestCase):

    def setUp(self):
        queue = Queue()
        self.spaces = Spaces()
        spaces_context = SpacesContext(self.spaces, queue)
        runtime = rt.Runtime()
        queue = Queue()
        runtime.spaces_context = SpacesContext(self.spaces, queue)
        initialise_spaces_with_local_config_files(runtime)

    def tearDown(self):
        self.uris = None
        try:
            os.remove(DATABASE_NAME)
        except:
            pass

    def test_get_class_type_case_1(self):
        '''[rt] test get class type where class exists'''
        runtime = rt.Runtime()
        queue = Queue()
        spaces = Spaces()
        runtime.spaces_context = SpacesContext(spaces, queue)
        class_type = runtime.get_class_type('runtime.rt', 'Runtime')
        self.assertEqual(str(class_type), str(type(runtime)))
    
    def test_get_class_type_case_2(self):
        '''[rt] test get class type where class doesnt exists'''
        runtime = rt.Runtime()
        queue = Queue()
        spaces = Spaces()
        runtime.spaces_context = SpacesContext(spaces, queue)
        try:
            runtime.get_class_type('runtime.rt', 'Blah')
        except AttributeError:
            assert True
    
    def test_create_task_case_1(self):
        '''[rt] test create task with valid task'''
        ds = DataStore(DATABASE_NAME)
        runtime = rt.Runtime()
        queue = Queue()
        spaces = Spaces()
        runtime.spaces_context = SpacesContext(spaces, queue)
        task_fully_qualified_path = 'services.httptask.HTTPTask'
        queue = Queue()
        spaces_context = SpacesContext(spaces, queue)
        spaces_context.load_bindings({'dummyprefix':'http://www.dummmy.com'})
        dummy_uri = spaces_context.uri('dummyprefix:')
        task_def_rs = Resource()
        instance = runtime.create_task(ds, spaces, task_fully_qualified_path, dummy_uri, task_def_rs)
        self.assertEqual(str(type(instance)), "<class '{0}'>".format(task_fully_qualified_path))
         
    def test_create_task_case_2(self):
        '''[rt] test create task with invalid task'''
        ds = DataStore(DATABASE_NAME)
        runtime = rt.Runtime()
        queue = Queue()
        spaces = Spaces()
        runtime.spaces_context = SpacesContext(spaces, queue)
        task_fully_qualified_path = 'datastore.resource.Resource'
        queue = Queue()
        spaces_context = SpacesContext(spaces, queue)
        spaces_context.load_bindings({'dummyprefix':'http://www.dummmy.com'})
        dummy_uri = spaces_context.uri('dummyprefix:')
        task_def_rs = Resource()
        try:
            runtime.create_task(ds, spaces, task_fully_qualified_path, dummy_uri, task_def_rs)
        except NonTaskException:
            assert True
    
    def test_initialise_spaces(self):
        '''[rt] test initialise_spaces'''
        ns = {
            'yarra':     'http://yarra-project.com/terms/yarra/',
            'datastore': 'http://yarra-project.com/terms/base/datastore/',
            'dc':        'http://purl.org/dc/elements/1.1/',
            'package':   'http://yarra-project.com/terms/base/package/'
        }

        type_a = {'package:label':'Type A',
                  'package:definition': 'Definition of Type A'}
        type_b = {'package:label':'Type B',
                  'package:definition': 'Definition of Type B'}
        spaces_dict = {'blah:type/typea':type_a,
                       'blah:type/typeb':type_b
                       }
        task_resource_a = Resource()
        task_resource_b = Resource()
        type_resource_a = Resource()
        type_resource_b = Resource()
        type_resource_a.set_var('package:manifest/spaces', type_a)
        type_resource_b.set_var('package:manifest/spaces', type_b)
        config_file = Resource(namespaces=ns)
        config_file.set_var('package:manifest/binding', 
                {'blah':'http://www.example.com/',
                'package':'http://yarra-project.com/terms/base/package/'})
        config_file.set_var('package:manifest/spaces', spaces_dict)
        config_file.set_metadata(
            Uri('package:packagename'),
            'new_package_name')
        config_file.set_metadata(
            Uri('package:projectname'), 
            'new_project_name')
        config_file.set_type(Uri('package:type/configuration'))
        
        spaces = Spaces()
        queue = Queue()
        spaces_context = SpacesContext(spaces, queue)
        
        # test passing in config files
        runtime = rt.Runtime()
        queue = Queue()
        runtime.spaces_context = SpacesContext(spaces, queue)
        runtime.initialise_spaces(config_file_rs_list=[config_file])
        blah_uri = spaces.uri('blah:')
        config_uri = spaces.uri('http://localhost:8000/configuration/')
        
        # test bindings loaded
        self.assertEqual(blah_uri.resource.type.full_uri(), 
                         'http://www.example.com/resource/type')
        # test config file added to spaces
        spaces_context.dump()
        self.assertEqual(spaces_context.get(config_uri.new_project_name.new_package_name), config_file)
        # test spaces def added to spaces
        self.assertEqual(spaces_context.get(blah_uri.type.typea), type_resource_a)
        self.assertEqual(spaces_context.get(blah_uri.type.typeb), type_resource_b)
        
    def test_create_tasks_from_configuration(self):
        '''[rt] test create_tasks_from_configuration'''
        task_a_uri = 'tasks:base/service/taska'
        task_b_uri = 'tasks:base/service/taskb'
        task_def_a = {'package:taskuri':task_a_uri,
                    'dc:description': 'description a',
                    'package:classname':'runtime.task.Task'
                    }
        task_def_b = {'package:taskuri':task_b_uri,
                    'dc:description': 'description b',
                    'package:classname':'runtime.task.Task'
                    }      
        config_file_rs = Resource()
        config_file_rs.set_var('package:manifest/tasks', [task_def_a, task_def_b])        
        runtime = rt.Runtime()
        queue = Queue()
        spaces = Spaces()
        runtime.spaces_context = SpacesContext(spaces, queue)
        tasks = runtime.create_tasks_from_configuration(config_file_rs)
        self.assertEqual(tasks[0].task_uri, self.spaces.uri(task_a_uri))
        self.assertEqual(tasks[1].task_uri, self.spaces.uri(task_b_uri))
    
#    def test_post_start_case_1(self):
#        '''[rt] test post_start shutdown'''
#        ds = DataStore(DATABASE_NAME)
#        queue_1 = Queue()
#        spaces_context_1 = SpacesContext(self.spaces, queue_1)
#        uri_tasks = spaces_context_1.uri('tasks:')
#        runtime = rt.Runtime()        
#        queue = Queue()
#        runtime.spaces_context = SpacesContext(self.spaces, queue)
#        quit_uri = Uri('http://blah/quit')
#        task_def_rs = Resource()
#        task_def_rs.set_type(uri_tasks.type.taskdef)
#        task_a = Task(ds, self.spaces, uri_tasks.base.service.a, task_def_rs)
#        task_b = Task(ds, self.spaces, uri_tasks.base.service.b, task_def_rs)
#        task_c = Task(ds, self.spaces, uri_tasks.eplanning.service.c, task_def_rs)
#        runtime.tasks.extend([task_a, task_b, task_c])
#        task_a.start()
#        task_b.start()
#        task_c.start()
##        spaces_context_1.process(quit_uri, get='cb_node_shutdown')        
#        def emulate_quit_request():
#            queue_2 = Queue()
#            spaces_context_2 = SpacesContext(self.spaces, queue_2)
#            time.sleep(2)
#            spaces_context_2.put(quit_uri, res=None)
#        thread.start_new_thread(emulate_quit_request, ())        
##        exit_code = runtime.post_start(spaces_context_1)
#        exit_code = runtime.post_start()
#        self.assertEqual(exit_code, 0)
#        self.assertFalse(task_a.isAlive())
#        self.assertFalse(task_b.isAlive())
#        self.assertFalse(task_c.isAlive())
        
#    def test_post_start_case_2(self):
#        '''[rt] test post_start restart'''
#        queue_1 = Queue()
#        spaces_context_1 = SpacesContext(self.spaces, queue_1)
#        runtime = rt.Runtime()        
#        restart_uri = Uri('http://blah/restart')
#        spaces_context_1.process(restart_uri, get='cb_node_shutdown')        
#        def emulate_quit_request():
#            queue_2 = Queue()
#            spaces_context_2 = SpacesContext(self.spaces, queue_2)
#            time.sleep(2)
#            spaces_context_2.get(restart_uri)
#        thread.start_new_thread(emulate_quit_request, ())        
#        exit_code = runtime.post_start(spaces_context_1)
#        self.assertEqual(exit_code, 1)        
    
if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()